home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 7
/
FM Towns Free Software Collection 7.iso
/
data
/
happypas
/
ticket.pas
< prev
Wrap
Pascal/Delphi Source File
|
1993-11-30
|
13KB
|
271 lines
{*********************************************************************
* *** 自動切符販売機のシミュレーション *** *
* *
* HAPPyのサンプルプログラム *
* (作者 浅野比富美 Public Domain Software) *
*********************************************************************}
program TicketSeller(input,output);
{ 120円、150円、160円、190円、210円、250円、290円という7種類の切符を売る自動販売
機があります。これら切符を購入しお釣りを出すプログラムです。
入れることのできるお金は10円、50円、100円、500円、1000円の5種類で、コインにつ
いては20枚まで、1000円札は1枚まで入れられます。
10円~500円玉は、お釣り用としてそれぞれ20個ずつ用意されているとします。
また、入れたお金はそのままお釣りとして使えるものとします。
もちろんお釣りはなるべく少ないコイン数になるよう調整します。
}
type kind = ( { 入力選択番号に使う}
y10 ,y50 ,y100,y500,y1000, { お金の種類 }
t120,t150,t160,t190,t210,t250,t290, { 切符の種類 }
cancel, { cancel ・・ 取消 }
finish { finish ・・ 終了 }
) ;
MoneyTable = array[y10..y1000] of integer ; {金種対応の枚数を格納}
var TKingaku : array[t120..t290] of integer ; { 切符の値段表 }
kingaku : array[y10..y1000] of integer ; { お金の値段表 }
store : MoneyTable ; { 金庫のお金の枚数 }
InCoin : MoneyTable ; { 投入されたお金の枚数 }
turi : MoneyTable ; { 釣銭の枚数 }
InPrice : integer ; { 投入された金額 }
TPrice : integer ; { 購入する切符の値段 }
oturi : integer ; { お釣り金額 }
InitCoin : integer ; { 最初の金庫金額合計 }
dummy : Boolean ; { ダミーフラグ }
{****************************************}
{* 金額合計を求める関数 *}
{****************************************}
function sum(number:MoneyTable) : integer;{ number の合計を返却 }
var y : y10..y1000 ; { for文の制御変数(金種) }
total : integer; { 計算エリア }
begin {sum}
total := 0 ;
for y := y10 to y1000 do total := total + number[y] * kingaku[y] ;
sum := total
end {sum};
{****************************************}
{* 初期設定 *}
{****************************************}
procedure init ;
var y : y10..y500 ; { for文の制御変数(金種) }
begin {init}
TKingaku[t120] := 120 ; TKingaku[t150] := 150 ; TKingaku[t160] := 160;
TKingaku[t190] := 190 ; TKingaku[t210] := 210 ; TKingaku[t250] := 250;
TKingaku[t290] := 290 ; { 切符の値段設定 }
kingaku[ y10] := 10 ; kingaku[ y50] := 50; kingaku[y100] := 100;
kingaku[y500] := 500 ; kingaku[y1000] := 1000; { お金の額面設定 }
for y := y10 to y500 do store[y] := 20 ;{ 10円から500円までは20枚 }
store[y1000] := 0 ; { 1000円は蓄えなし }
InitCoin := sum(store) { 最初の金庫合計を算出 }
end {init} ;
{****************************************}
{* 金種の出力 *}
{****************************************}
procedure PrintCoin(print:MoneyTable) ; { print : 出力対象 }
var y : y10..y1000 ; { for文の制御変数(金種) }
begin {PrintCoin}
if sum(print) = 0 then writeln { 0円ならば出力しない }
else
begin
write('(') ;
for y := y1000 downto y10 do { それぞれの金種について }
if print[y] <> 0 then write(kingaku[y]:2,'円=',print[y]:1,'枚 ');
writeln(')')
end
end {PrintCoin} ;
{****************************************}{ oturiが、bankから払えれば真を}
{* 釣銭の計算 *}{ 返す。 釣銭の金種はturiに格納}
{****************************************}{ bankは釣銭支払い後の状態になる}
function CompTuri(oturi:integer ; var bank:MoneyTable) : Boolean ;
var d : integer ; { 計算エリア }
y : y10..y1000 ; { for文の制御変数(金種) }
SaveY1000 : integer ; { 金庫の1000円枚数退避用 }
begin {CompTuri}
SaveY1000 := bank[y1000] ; { 今の1000円札を退避 }
for y := y10 to y500 do { 釣銭として使えるお金を求める }
bank[y] := bank[y] + InCoin[y] ; { 10~500円は金庫と投入コイン }
bank[y1000] := InCoin[y1000] ; { 1000円札は今入れられたもの }
for y := y1000 downto y10 do { 1000円から順に釣りを計算 }
begin
d := oturi div kingaku[y] ; { 必要コイン数 }
if d > bank[y] then d := bank[y] ; { 金庫のコイン全部 }
bank[y] := bank[y] - d ; { 必要コインを引く }
turi[y] := d ; { 釣銭を格納 }
oturi := oturi - (kingaku[y] * d) { 残りのお釣り計算 }
end ;
bank[y1000] := bank[y1000] + SaveY1000 ; { 1000円札の枚数更新 }
CompTuri := oturi = 0 { 釣銭不足でなければ真 }
end {CompTuri};
{****************************************}
{* 入力操作 *}
{****************************************}
function operation : Boolean ; { 終わりが選択されたら偽を返す }
const MaxCoin = 20 ; { 最大コイン投入可能枚数 }
var t : t120..t290 ; { for文の制御変数(切符の種類) }
n : integer ; { 入力番号 }
s : kind ; { 選択番号 }
oturi : integer ; { お釣り金額 }
TempStore : MoneyTable ; { storeのワーク }
number : integer ; { お金の枚数 }
CoinNumber : integer ; { コイン枚数投入の管理に使用 }
ok : Boolean ; { 選択番号入力okフラグ }
selector : set of kind ; { 入力可能な選択番号集合 }
{************************************}
{* 投入コインエリアのクリア処理 *}
{************************************}
procedure clear ;
var y : y10..y1000 ; { for文の制御変数(金種) }
begin {clear}
CoinNumber := 0 ; { 投入コイン枚数クリア }
for y := y10 to y1000 do InCoin[y] := 0 ;
selector := [y10..y1000,finish] { 最初に選べる選択番号集合 }
end {clear} ;
{************************************}
{* 入力不可の項目に*を付ける処理 *}
{************************************}
procedure PutAster(s:kind) ; { sが不可の時 * をつける }
begin {PutAster}
if s in selector then write(' ') else write('*')
end {PutAster} ;
{************************************}
{* 釣銭切れ出力 *}
{************************************}
procedure OutOfTuri ;
var y : y10..y500 ; { for文の制御変数(金種) }
fusoku : Boolean ; { 釣銭切れがある時 真 }
begin {OutOfTuri}
fusoku := false ;
for y := y10 to y500 do { 釣銭切れがあるか調べる }
fusoku := fusoku or (store[y]+InCoin[y] = 0) ;
if fusoku then { 釣銭切れがある時 }
begin
write('釣銭切れ (') ;
for y := y10 to y500 do { 釣銭切れのお金を表示 }
if store[y] + InCoin[y] = 0 then write(kingaku[y]:2,'円 ') ;
writeln(')')
end
end {OutOfTuri} ;
{************************************}
{* 選択番号のガイドを出力する処理 *}
{************************************}
procedure guide ;
var y : y10..y1000 ; { for文の制御変数(金種) }
t : t120..t290 ; { for文の制御変数(切符の種類) }
begin {guide}
writeln ;
write('投入金額=',InPrice:4,'円 ');
PrintCoin(InCoin) ; { 投入コインの詳細を出力 }
OutOfTuri ; { 釣銭切れ情報出力 }
writeln(
'========================= 切符販売機 選択番号一覧 =========================');
write('金種選択('); { 金種選択の番号出力 }
for y := y10 to y1000 do
begin
PutAster(y) ; write(ord(y):1,':',kingaku[y]:3,'円 ')
end ;
writeln(')');
write('切符選択('); { 切符選択の番号出力 }
for t := t120 to t290 do
begin
PutAster(t) ; write(ord(t):1,':',TKingaku[t]:3,'円 ')
end;
writeln(')');
write('その他 ( '); { その他の番号出力 }
PutAster(cancel) ; write(ord(cancel):2,': 取消 ');
PutAster(finish) ; writeln(ord(finish):2,': 終わり )');
writeln(
'===========================================================================')
end {guide} ;
begin {operation ---------入力操作のメイン処理-------------------------}
writeln ;
clear ; { 投入コインエリアのクリア }
repeat { 切符選択または終わりまで }
InPrice := sum(InCoin) ; { 投入合計金額を計算 }
if InPrice <> 0 then selector := selector+[cancel] ;{取消有効 }
if CoinNumber = MaxCoin then selector := selector-[y10..y500] ;{コイン不可}
for t := t290 downto t120 do { 釣銭不足とならないか調べる }
begin
oturi := InPrice - TKingaku[t] ; { お釣りを仮定する }
if oturi >= 0 then { 金額的に購入可能な時 }
begin
TempStore := store ; { 釣銭が出せるか調べる }
if CompTuri(oturi,TempStore) then { 釣銭が出せる }
selector := selector + [t] { その切符は購入可能 }
end
end ;
guide ; { 選択番号ガイド出力 }
ok := false ;
repeat { 正しい選択番号が入力されるまで}
write('選択番号を入力して下さい(*印の番号は入力不可) ? ') ;
readln(n) ; { 選択番号を入力 }
if (ord(y10) <= n) and (n <= ord(finish)) then
begin { 選択番号に対応した種別を得る }
s := y10 ; while ord(s) <> n do s := succ(s) ;
ok := s in selector { 入力可能な選択番号の時リピート抜け}
end
until ok ;
selector := selector - [finish] ; { 終わりを選べなくする }
if s = cancel then { 取消が選択された }
begin
write('投入された',InPrice:2,'円を返却します ') ;
PrintCoin(InCoin) ; { 投入コインの種別を出力 }
clear { 投入コインエリアをクリア }
end
else if s in [y10..y500] then { 10円~500円が選択された }
begin
repeat { MaxCoin枚まで }
write(kingaku[s]:2,'円を何枚入れますか (1~',
MaxCoin-CoinNumber:2,') ? ') ;
readln(number) { 枚数入力 }
until (1<=number) and (number<=MaxCoin-CoinNumber) ;
InCoin[s] := InCoin[s] + number; { 投入コインに加える }
CoinNumber := CoinNumber + number { 投入コイン枚数カウントアップ }
end
else if s = y1000 then { 1000円は1枚しか入らない }
begin
Incoin[y1000] := Incoin[y1000] + 1 ;
selector := selector - [y1000] { 以後1000円札投入不可 }
end
until s in [t120..t290,finish] ; { 切符、終わりが選ばれたら止める}
writeln ;
if s <> finish then TPrice := TKingaku[s] ;{ 切符の値段 }
operation := s <> finish { 終わりでなければ 真 }
end {operation};
{****************************************}
{* メイン処理 *}
{****************************************}
begin {main}
init ; { 初期設定 }
while operation do { 終わりが指示されるまで発券 }
begin
writeln(TPrice:3,'円の切符を発券します ');
oturi := InPrice - TPrice ;
write('釣銭は',oturi:2,'円 ') ; { 釣銭合計を表示 }
dummy := CompTuri(oturi,store) ; { 釣銭計算 (必ず釣銭が出せる) }
PrintCoin(turi) { 釣銭詳細を表示 }
end ;
writeln('営業終了'); { 終了処理 }
writeln(' 売上金 = ',sum(store)-InitCoin:5,'円'); { 売上金額表示 }
writeln(' 金庫の中 = ',sum(store):5,'円'); { 金庫の合計金額}
PrintCoin(store) { 金庫のお金の詳細を表示 }
end {main}.